Skip to content

feat(rails): pause on user input + sends gate for approval - #87

Merged
siddWednesday merged 6 commits into
feat/windows-parityfrom
feat/rails-input-pause
Aug 27, 2026
Merged

feat(rails): pause on user input + sends gate for approval#87
siddWednesday merged 6 commits into
feat/windows-parityfrom
feat/rails-input-pause

Conversation

@siddWednesday

Copy link
Copy Markdown
Collaborator

What this does

Two production-readiness fixes for the rails, both verified by hand on a live dev build (2026-08-27):

1. Pause when the user touches the machine - the documented defense, now wired. SAFETY_REVIEW promised "any user touch pauses the supervised run"; only the overlay's Pause button actually did. Now a watchdog shared by the vision and AX hosts pauses the guard on any human mouse/keyboard input. Telling human input from the rail's own output has one owner: the actuation adapter brackets every synthetic action (in-flight + parked cursor) in a tracker the watchdog consults - so the rail never pauses itself, and clicks on our own overlay (Resume) never re-pause. Detection is uiohook-napi (new OPTIONAL native addon, loaded by-variable like nut-js) for mouse + keyboard, with a dependency-free cursor-poll fallback for mouse. Esc remains the kill switch either way.

2. Sends gate for approval alongside computer_task. The shipped policy had drifted: mail_send / messages_send ran with no human in the loop while the safety review and the model-facing prompts promised gating. One rule now (gate-host needsApproval): computer-use rails AND send action types gate; web_task stays unprompted (it acts inside Off Grid's own watched pane and hands back at sign-in/payment); undoable mutations (calendar, reminders) keep the auto-run + Undo tier. The pro auto-approve toggle is scoped to computer use only - sends ask every time. Model hints and SAFETY_REVIEW now state exactly this policy.

Verification

  • Hand-verified live: email/iMessage sends parked at the approval card (approve runs, reject drops), calendar auto-ran with Undo, web_task unprompted; mid-computer_task mouse movement paused the run instantly, overlay Resume continued without re-pausing, Esc halted.
  • 42 new/updated tests: the takeover decision matrix (in-flight suppression, grace window, cursor tolerance, own-window rejection), the poll-strategy watchdog against a real tracker with fake Electron boundaries, the gate policy matrix, and sends parking even in auto mode. Rails area total: 281 passing.
  • Known follow-up for the real-machine pass: keyboard pause needs the macOS Input Monitoring grant (the uiohook path); mouse pause and Esc work without it.

🤖 Generated with Claude Code

siddWednesday and others added 2 commits August 27, 2026 14:40
Closes the documented-but-unwired defense (SAFETY_REVIEW 'any user touch
pauses'): a watchdog shared by the vision and AX hosts pauses the guard on
human input. Synthetic suppression has one owner - the actuation adapter
brackets every action in a tracker (in-flight + parked cursor), so the
rail's own output never reads as a takeover, and neither do clicks on our
own overlay (or resuming would instantly re-pause). Detection: uiohook-napi
(new OPTIONAL native addon, same load-by-variable pattern as nut-js) for
mouse + keyboard; a dependency-free cursor-poll fallback covers mouse when
the addon is absent. 15 tests over the decision rule and the poll path;
the hook path is owned by the real-machine pass like actuation itself.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The approval policy diverged from the safety story: mail_send and
messages_send ran with no human in the loop while every doc and the
model-facing prompts promised gating. One rule now, in needsApproval:
computer-use rails AND send action types gate; web_task stays unprompted
(it acts in Off Grid's own watched pane); undoable mutations keep the
auto-run + Undo tier. The pro auto-approve toggle is scoped to computer
use only - sends ask every time. Model hints and SAFETY_REVIEW updated to
say exactly this. Tests: the policy matrix + sends parking (even in auto
mode) + resolve round-trips.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@qodo-code-review

Copy link
Copy Markdown

ⓘ Qodo reviews are paused because your trial has ended. Ask your workspace admin to add credits to resume reviews. Manage billing

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your trial has ended. Reactivate Greptile to resume code reviews.

@coderabbitai

coderabbitai Bot commented Aug 27, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: c52953d1-c46b-4c41-8557-e2e489ab25b1

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your trial has ended. Reactivate Greptile to resume code reviews.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your trial has ended. Reactivate Greptile to resume code reviews.

… left behind

The planning pass (shouldPlan -> planTask) was consuming every tools-loop
test's first scripted turn - the fake llama now answers PLAN_SCHEMA
requests out-of-band with an empty plan (recorded separately as
plannerRequests), so tests drive the reactive loop they script. The
gate-seam journey's fixture becomes a SEND ('email') - under the current
policy only sends and computer-use gate, so that is the type that parks.
Both files were red on feat/windows-parity already (db suite is
non-blocking on push and the branch never ran CI); 29/29 now pass.
fresh-setup-first-use still fails on the base branch (pre-existing,
'LLM Service not ready' after relaunch) - tracked separately.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your trial has ended. Reactivate Greptile to resume code reviews.

The orchestrator's plan-executor imported ToolCall/UnifiedSource from the
big tools.ts, which imports the executor back - a no-circular violation the
dependency-boundaries gate rejects. Move the two shared leaf types to
tools/tool-types.ts (imported by both, importing nothing back); tools.ts
re-exports them so external importers are unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your trial has ended. Reactivate Greptile to resume code reviews.

@sonarqubecloud

Copy link
Copy Markdown

@siddWednesday
siddWednesday merged commit ab744b8 into feat/windows-parity Aug 27, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant